<?php

namespace app\common\controller\publics;

use think\App;
use think\Controller;
use think\Db;
use think\Request;

class GetTree
{
    private $pid='type_parent_id';
    private $id='type_id';
    private $config=[
        'tableName' => 'com_type'
    ];
    private $argument=[];

    public function __construct($C=array())
    {
        if (is_array($C)){
            foreach ($C as $key => $value){
                $this->config[$key] = $value;
                ($key=='pid') and ($this->pid=$value);
                ($key=='id') and ($this->id=$value);
            }
        }
        //parent::__construct($app);
    }
    public function set_config($C){
        if (is_array($C)){
            foreach ($C as $key => $value){
                $this->config[$key] = $value;
                ($key=='pid') and ($this->pid=$value);
                ($key=='id') and ($this->id=$value);
            }
        }
        return $this;
    }
    public function get_config($key){
        return empty($key) ? $this->config : $this->config[$key] ;
    }
    public function set_data($key='key',$value=''){
        if(!empty($key)){
            $this->argument[$key] = $value;
        }
        return $this;
    }
    public function get_data($key){
        return empty($key) ? $this->argument : $this->argument[$key] ;
    }


    /**
     * 无限级分类树
     * @$arr   array  传入二维数，里面的一维数组存在父id和id
     * @$pid   string 父id
     * @$di    string id
     * @return array 返回树型结构的数组（多维数组）
     */
    public function get_tree($arr){
        $items=[];
        $pid=$this->pid;
        $id=$this->id;
        foreach ($arr as $key => $value) {
            $items[$value[$id]] = $value;
        }
        $tree = array(); //格式化好的树
        foreach ($items as $key => $item){
            if (isset($items[$item[$pid]])){
                $items[$item[$pid]]['is_have_child'] = 1;  //标记改元素有子元素
                $items[$item[$pid]]['child'][] = &$items[$item[$id]];
            }
            else{
                $tree[] = &$items[$item[$id]];
            }
        }
        return $tree;
    }


    /**
     * 给树形结构的多维数组添加属性 leval,add_str,用于分级列表显示
     * @$treeArr	    array  多维数组（树形结构的多维数组，结合方法 self::get_tree() ）
     * @$lv	        number  用于记录子元素所在的层级
     * @$str1       string
     * @$str2       string
     */
    public function set_leval(&$treeArr,$lv=0,$str1='&nbsp;&nbsp;&nbsp;&nbsp;',$str2=' └ '){
        foreach ($treeArr as $key => $value){
            if (isset($value['child'])){
                self::set_leval($treeArr[$key]['child'],$lv+1,$str1,$str2);
            }
            $treeArr[$key]['leval'] = $lv;
            $treeArr[$key]['add_str'] = self::add_str($lv,$str1,$str2);
        }
    }


    /**
     * @$new_arr    array       引用传入一个数组，用来组成一个新的二维数组(一个有层次的二维数组)
     * @$arrTree    array       树型结构的数组，多维数组，配合方法 get_tree() 使用
     * @$data       array       二维数组，从数据库获取的多条记录
     */
    public function tree_leval(&$new_arr,$arrTree,&$data){
        $pid = $this->pid;
        $id = $this->id;
        foreach ($arrTree as $key => $value) {
            if (isset($value['child'])){
                $value_copy=$value;
                /*$value_copy['leval']= self::get_id_leval($value[$id],$data);*/
                unset($value_copy['child']);
                $new_arr[]=$value_copy;
                unset($value_copy);
                self::tree_leval($new_arr,$value['child'],$data);
            }
            else{
               /* $value['leval']= self::get_id_leval($value[$id],$data);*/
                $new_arr[]=$value;
            }
        }
    }


    /**
     * 获取当前id 所属的层级(与方法 self::tree_leval() 组合搭配使用)
     * @$id_value    string 当前id的值
     * @$arrLv2      array   二维数组，从数据库读取的多条记录数据
     * @return number
     */
    public function get_id_leval($id_value,&$arrLv2){
        $leval=0;
        $id = $this->id;
        $pid = $this->pid;
        self::get_parent($arrLv2,$id_value,$leval,$pid,$id);
        return $leval-1;
    }
    private function get_parent(&$arrLv2,$id_value,&$lv,$pid,$id){
        foreach ($arrLv2 as $key => $value){
            if ($value[$id]==$id_value){
                $lv++;
                $parent_id = $value[$pid];
                foreach ($arrLv2 as $k => $v){
                    if ($v[$id]==$parent_id){
                        $parent = $v;
                        break;
                    }
                }
                break;
            }
        }
        if (isset($parent[$pid]) && $parent[$pid] != $parent[$id]){
            self::get_parent($arrLv2,$parent[$id],$lv,$pid,$id);
        }
        else{
            return $lv;
        }
    }


    /**
     * 获取 父id 里面的所有 子id
     * @$pid_value	    number  要查找的父id的id值
     * @$data	        array   二维数组,从数据库读取的多条记录数据(里面的一维关联数组存在父id和id)
     * @return array  二维数组
     */
    public function get_all_child($pid_value,$data){
        $new_arr=['temporary'=>[],'create_arr'=>[]];
        $pid=$this->pid;  $id=$this->id;

        self::gac($pid_value,$data,$new_arr,$pid,$id);
        return $new_arr['create_arr'];
    }
    private function gac($pid_value,$data,&$new_arr,$pid,$id){
        foreach ($data as $key => $value) {
            if ($value[$pid] == $pid_value){
                $new_arr['create_arr'][]=$value;
                unset($data[$key]);
                if(isset($value['is_have_child'])){
                    foreach ($data as $k => $v){
                        //判断选中的是否还是另外元素的父id
                        if($v[$pid]==$value[$id]){
                            self::gac($value[$id],$data,$new_arr,$pid,$id);
                        }
                    }
                }
            }
        }
    }


    /**
     * 获取多级列表 (数据库表 sz_com_type)
     * @$id_v       string id值，主要给该id值下的所有子元素设置 disabled 属性值为 1
     * @$lv         number 要显示的列表缩进级别
     * @data        array  二维数组，里面的一维数组存在父id和id
     * @return      array  返回有层次的二维数组
     */
    public function get_leval_list($id_v=1,$lv=2,$data='',$str1='&nbsp;&nbsp;&nbsp;&nbsp;',$str2=' └ '){
        $pid=$this->pid;
        $id=$this->id;
        $tableName = $this->config['tableName'];
        empty($id_v) and ($id_v=1);
        //$parent = db('com_type')->field('type_id,type_name,type_org_type,type_org_id')->where('type_parent_id','=','0')->select();
        if(is_array($data)){
            foreach ($data as $key => $value) {
                if($value[$id]==$id_v){
                    $table_data=$value;
                    break;
                }
            }
            unset($key,$value);
        }
        else{
            $table_data = \db($tableName)->where($id,'=',$id_v)->find();
            $data = db($tableName)->select();
        }

        //生成新的拥有层次的二维数组 ( $new_arr )
        $treeArr = $this->get_tree($data);
        $this->set_leval($treeArr,0,$str1,$str2);
        $this->tree_leval($new_arr=[], $treeArr, $data);

        //筛选要渲染的元素（下面只显示二级缩进 列表）
        foreach ($new_arr as $key => $value) {
            //if ($this->get_id_leval($value[$id],$data) > $lv ){
            //    unset($data[$key]);
            //}
            if($value['leval'] >$lv){
                unset($new_arr[$key]);
            }
        }

        //获取该元素的子元素的id值(type_id),一维数组
        //if (!isset($table_data[$id])){return false;};
        if (isset($table_data[$id])){
            $child_arr['c'] = self::get_all_child($table_data[$id],$new_arr);
            foreach ($child_arr['c'] as $key => $value) {
                $child_arr['n'][] = $value[$id];
            }
            isset($child_arr['n']) or ($child_arr['n']=[]);
            //给新数组添加属性方便前台模板渲染
            foreach ($new_arr as $key => $value) {
                $new_arr[$key]['disabled']= in_array($value[$id],$child_arr['n'])  ? 1 : 0;
            }
            unset($child_arr);
        }
        return $new_arr;
    }
    public function add_str($lv,$str1='&nbsp;&nbsp;&nbsp;&nbsp;',$str2=' └ '){
        for ($i=0,$st=''; $i < $lv; $i++) {
            $st.=$str1;
        }return $lv>0 ? $st.$str2 : '';
    }

    /**
     * 获取某个父id的分级列表
     * @$pid_value  number  父id值
     * @$lv         number 要显示的列表缩进级别
     * @data        array  二维数组，里面的一维数组存在父id和id
     * @return      array  返回有层次的二维数组
     */
    public function get_parent_leval_list($pid_value,$lv=2,$data=array(),$str1='&nbsp;&nbsp;&nbsp;&nbsp;',$str2=' └ '){
        $new_data = self::get_all_child($pid_value,$data);
        foreach ($data as $key => $value) {
            if ($value[$this->id] == $pid_value){
                $new_data[] = $value;
                break;
            }
        }
        return self::get_leval_list($pid_value,$lv,$new_data,$str1,$str2);
    }

    /**
     * 检查 id值是否存在
     * @$id_value    number  id值
     * @$data        array  二维数组，里面的一维数组存在父id和id
     * @return      boolean|array  返回false或者一维数组
     */
    public function is_have_id($id_value,$data){
        if (is_array($data)){
            foreach ($data as $key => $value) {
                if (isset($value[$this->id]) && $value[$this->id]==$id_value){
                    return $value;
                }
            }
        }
        return false;
    }


    /**
     * 检查某个字段的值是否存在，存在则返回一个二维数组
     * @$key        string          字段名
     * @$value      stirng|array    字段值，字符串或者一维数组(可以对比多个值)
     * @data        array           二维数组，里面的一维数组存在父id和id
     * @return      array|boolean   返回二维数组或者布尔值false
     */
    public function is_have_values($key,$value,$data){
        if (isset($value)){
            $in = is_array($value) ? $value : [$value] ;
            foreach ($data as $k => $v) {
                if (in_array($v[$key],$in)){
                    $arr[] = $v;
                }
            }
        }
        return isset($arr) && is_array($arr) ? $arr : false;
    }
    /**
     * 检查某个字段的值是否存在
     * @$key        string          字段名
     * @$value      stirng|array    字段值，字符串
     * @$data       array           数组或者为空
     * @return      array|boolean   返回数组($data的值为二维数组或多维数组时)或者布尔值
     * @用法1 $this->set_data('data',array())->is_have_value('key','value');
     * @用法2 $this->is_have_value('key','value',array());
     */
    public function is_have_value($key,$value,$data=''){
        $data = is_array($data) ? $data : self::get_data('data');
        if (is_array($data) && $this->arrayLevel($data)==1 ){
            return in_array($value,$data);
        }
        if (is_array($data) && $this->arrayLevel($data)>1 ){
            foreach ($data as $k => $v) {
                if ($v[$key] == $value){
                    return $v;
                }
            }
        }
        return false;
    }


    /**
     * 返回数组的维度
     * @$arr    array   数组
     * @return  number  数组的维度
     */
    public function arrayLevel($arr){
        $al = array(0);
        self::aL($arr,$al);
        return max($al);
    }
    private function aL($arr,&$al,$level=0){
        if(is_array($arr)){
            $level++;
            $al[] = $level;
            foreach($arr as $k => $v){
                self::aL($v,$al,$level);
            }
        }
    }


}
